/**
  * 16.4 类型投影
  * 类型投影(type projection)
  * 在 scala 里，内部类型(排除定义在 object 内部的)，想要表达所有的外部
  * 类 A 实例路径下的 B 类型，即对 a1.B 和 a2.B 及所有的 an.B 类型找一个共同
  * 的父类型，这就是类型投影，用 A#B 的形式表示。
  *    A#B
  *    / \
  *   /   \
  * a1.B a2.B
  * 这样，我们只要修改一下 foo 方法里的参数类型
  * def foo(b: A#B)
  * 就可以调用 a1.foo(b2) 了。
  * 我们回头来对比一下 scala 里的类型投影与 java 里的内部类型的概念，
  * java 里的内部类型在写法上是 Outter.Inner 它其实等同于 scala 里的投影类型
  * Outter#Inner， java 里没有路径依赖类型的概念，比较简化。
  * 对于嵌套类的问题，对于每一个对象的内部类类型是不一样的。如下：
  */

import scala.collection.mutable.ArrayBuffer

class Network {
  class Member(val name: String) {
    //val contacts = new ArrayBuffer[Member]
    val contacts = new ArrayBuffer[Network#Member]//类型投影定义为 Network#Member，表示为任何 Network 的 Member。
    override def toString = getClass.getName + "[name=" + name + 
      ",contacts=" + contacts.map(_.name).mkString("[", ",", "]") + "]"
  }

  private val members = new ArrayBuffer[Member]

  def join(name: String) = {
    val m = new Member(name)
    members += m
    m
  }

  override def toString = getClass.getName + "[members=" + members + "]"
}

val chatter = new Network
val myFace = new Network
/*
chatter.Member 和 myFace.Member 是不同的类。
类型投影定义为 Network#Member，表示为任何 Network 的 Member。
 */



val fred = chatter.join("Fred")
val wilma = chatter.join("Wilma")
fred.contacts += wilma // OK
val barney = myFace.join("Barney")
fred.contacts += barney // Also OK

println("chatter=" + chatter)
println("myFace=" + myFace)
